Next | Prev | Up | Top | Contents | Index

Example Program

Suppose the mythical VT device wants to share memory with a user program. Its drvmap() and drvunmap() functions would look something like this:

#include <sys/sysmacros.h>
struct mpd {
   unsigned int d_id;    /* id of memory segment */
   caddr_t  d_addr;      /* address of allocated memory */
   int      d_npages;    /* number of pages allocated */
   struct mpd *d_last, *d_next;   /* links */
};

struct mpd vdk_list;    /* at init, this becomes a doubly 
                        /*linked ring */

int vdkmap(dev_t dev, vhandl_t *vt, off_t off, int len, 
           int prot)
{
   struct mpd *d;

   /* initial sanity checking (not shown) */
   ...

   /* allocate some temporary storage */
   if( (d = kmem_alloc(sizeof(struct mpd)), 0 ) 
      == NULL )
      return ENOMEM;

   d->d_npages = btoc(len);
   if( (d->d_addr = kmem_alloc(ctob(d->d_npages))KM_CACHEALIGN) == NULL ) {
      kmem_free(d,sizeof(struct mpd));
      return ENOMEM;
   }

   /* map it into the user's address space */
   if( v_mapphys(vt,d->d_addr,len) ) {
      kmem_free(d->d_addr,ctob(d->d_npages));
      kmem_free(d,sizeof(struct mpd));
      return ENOMEM;
   }

   d->d_id = v_gethandle(vt);

   /* initialize the memory */
   bzero(d->d_addr,ctob(d->d_npages));

   /* add to the list */
   d->d_next = vdk_list.d_next;
   d->d_last = &vdk_list;
   d->d_next->d_last = d->d_last->d_next = d;

   return 0;
}
See "Returning Opaque Handle Data," for a description of the v_gethandle() system function. In the vdkunmap() function, you can find the piece of memory to be deallocated by searching the above list. The driver can then call the kmem_free() kernel function with the address and length of this section of memory:

int vdkunmap(dev_t dev, vhandl_t *vt)
{
   struct mpd *d;
   int id;

   id = v_gethandle(vt);

   /* Find chunk of memory corresponding to it. */
   for(d = vdk_list.d_next; d != &vdk_list ; d = d->d_next )
      if( d->d_id == id )
         break;
      
   /* Make sure we found it. */
   if( d == &vdk_list )
      return 0;

   /* remove from list */
   d->d_next->d_last = d->d_last;
   d->d_last->d_next = d->d_next;

   /* free up resources */
   kmem_free(d->d_addr,ctob(d->d_npages));
   kmem_free(d,sizeof(struct mpd));

   return 0;
}


Next | Prev | Up | Top | Contents | Index